package cn.miju.unionpay.handler;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import cn.miju.common.content.CodeMessage;
import cn.miju.common.util.OkHttpUtil;
import cn.miju.common.util.ValidationUtil;
import cn.miju.unionpay.constant.UnionPayConstant;
import cn.miju.unionpay.model.*;
import cn.miju.unionpay.properties.UnionPayProperties;
import cn.miju.unionpay.request.UnionPayApplyQrCodeReq;
import cn.miju.unionpay.response.UnionPayApplyQrCodeResp;
import cn.miju.unionpay.response.UnionPayBaseResp;
import cn.miju.unionpay.util.UnionPaySignUtil;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.Set;

/**
 * <pre>
 * 申请支付二维码
 * </pre>
 *
 * @author zhuming
 * @version 1.0.0
 * @since 2023-03-13 16:16
 */
@Slf4j
@Component
public class UnionPayApplyQrCodeHandler extends AbstractUnionPayHandler<UnionPayApplyQrCodeReq, UnionPayApplyQrCodeResp> {
    /**
     * 可选返回参数(如果接口所需参数不满足需求，可按照官方接口文档，原样传入对应参数)
     */
    private Set<String> optionalRespParams;
    /**
     * 请求参数前置处理
     * @param req 请求参数
     * @return 结果
     */
    @Override
    public ApplyQrCodeRequest beforeRequest(UnionPayApplyQrCodeReq req) {
        ValidationUtil.validate(req);
        UnionPayProperties unionPayProperties = req.getUnionPayProperties();
        UnionPayRequest request = super.beforeRequest(req);
        request.setTxnType(UnionPayConstant.TxnType.CONSUME);
        request.setTxnSubType(UnionPayConstant.TxnSubType.APPLY_CONSUME_QRCODE);
        request.setBizType(UnionPayConstant.BizType.DEFAULT);
        request.setChannelType(UnionPayConstant.ChannelType.MOBILE);
        request.setCurrencyCode(UnionPayConstant.CURRENCY_CODE);
        request.setMerId(unionPayProperties.getMerchantNo());
        ApplyQrCodeRequest applyQrCodeRequest = BeanUtil.copyProperties(request, ApplyQrCodeRequest.class);
        applyQrCodeRequest.setOrderId(req.getOutTradeNo());
        applyQrCodeRequest.setTxnAmt(String.valueOf(req.getTotalAmount()));
        AcqAddnData acqAddnData = new AcqAddnData();
        AcqAddnData.OrderInfo orderInfo = new AcqAddnData.OrderInfo();
        orderInfo.setTitle(req.getTitle());
        orderInfo.setDescription(req.getDescription());
        acqAddnData.setOrderInfo(JSONObject.toJSONString(orderInfo));
        applyQrCodeRequest.setAcqAddnData(Base64.encode(JSONObject.toJSONString(acqAddnData)));
        if (req.getTimeExpire() != null) {
            LocalDateTime payTimeout = (req.getTimeExpire() == null || req.getTimeExpire() > 86400) ? null : LocalDateTime.now().plusSeconds(req.getTimeExpire());
            applyQrCodeRequest.setPayTimeout(payTimeout == null ? null : payTimeout.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        }
        applyQrCodeRequest.setBackUrl(StringUtils.isBlank(req.getNotifyUrl()) ? UnionPayConstant.DEFAULT_BACK_URL : req.getNotifyUrl());
        optionalRespParams = req.getOptionalRespParams();
        super.setOptionalReqParams(applyQrCodeRequest, req.getOptionalReqParams());
        return applyQrCodeRequest;
    }

    /**
     * 核心执行
     *
     * @param req {@link UnionPayApplyQrCodeReq}
     * @return {@link UnionPayApplyQrCodeResp}
     */
    @Override
    public UnionPayApplyQrCodeResp doPlan(UnionPayApplyQrCodeReq req) {
        UnionPayProperties unionPayProperties = req.getUnionPayProperties();
        ApplyQrCodeRequest request = this.beforeRequest(req);
        // 签名
        Map<String, String> param = JSONObject.parseObject(JSONObject.toJSONString(request), Map.class);
        UnionPaySignUtil.sign(param, unionPayProperties.getSignCertPath(), unionPayProperties.getSignCertPwd());
        String reqParam = UnionPaySignUtil.createLinkString(param, false, true, StandardCharsets.UTF_8.toString());
        // 请求
        log.info("API--申请二维码(主扫)--> Request：{}", reqParam);
        String result = OkHttpUtil.doPost(unionPayProperties.getServiceUrl(), reqParam);
        log.info("API--申请二维码(主扫)--> Response：{}", result);
        if (StringUtils.isBlank(result)) {
            return UnionPayApplyQrCodeResp.builder().code(CodeMessage.FAIL.getCode()).msg("响应数据为空").build();
        }
        ApplyQrCodeResponse response = JSONObject.parseObject(JSONObject.toJSONString(UnionPaySignUtil.readLinkStr(result)), ApplyQrCodeResponse.class);
        return this.afterResponse(response);
    }

    /**
     * 响应参数后置处理
     *
     * @param resp 响应参数
     * @return 结果
     */
    @Override
    public UnionPayApplyQrCodeResp afterResponse(UnionPayResponse resp) {
        UnionPayBaseResp baseResp = UnionPayBaseResp.preBuilder(CodeMessage.FAIL);
        ApplyQrCodeResponse response = (ApplyQrCodeResponse) resp;
        if (StringUtils.isNotBlank(response.getRespMsg())) {
            baseResp.setMsg(response.getRespMsg());
        }
        if (response.isSuccess()) {
            baseResp = UnionPayBaseResp.preBuilder(CodeMessage.SUCCESS);
            baseResp.setOptionalRespParams(super.getOptionalRespParams(response, optionalRespParams));
        }
        UnionPayApplyQrCodeResp unionPayApplyQrCodeResp = BeanUtil.copyProperties(baseResp, UnionPayApplyQrCodeResp.class);
        unionPayApplyQrCodeResp.setOutTradeNo(response.getOrderId());
        unionPayApplyQrCodeResp.setQrcode(response.getQrCode());
        return unionPayApplyQrCodeResp;
    }
}
